package com.bytecub.udp.service.parser;

import com.bytecub.common.constants.BCConstants;
import com.bytecub.common.enums.BCErrorEnum;
import com.bytecub.common.exception.BCGException;
import com.bytecub.protocol.base.IBaseProtocol;
import com.bytecub.protocol.domain.bo.DeviceProductBo;
import com.bytecub.protocol.service.IProtocolUtilService;
import com.bytecub.udp.domain.bo.ParseDeviceBo;
import com.bytecub.utils.JSONProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 *  * ByteCub.cn.
 *  * Copyright (c) 2020-2021 All Rights Reserved.
 *  * 定位到产品
 *  * @author bytecub@163.com  songbin
 *  * @Date 2021/4/2  Exp $$
 *  
 */
@Slf4j
@Service
public class UdpProtocolParser {
    @Autowired
    IProtocolUtilService protocolUtilService;

    public ParseDeviceBo parseProtocol(byte[] content){
        ParseDeviceBo parseDeviceBo = new ParseDeviceBo();
        String deviceCode = this.parseDeviceCode(content);
        if(StringUtils.isEmpty(deviceCode)){
            throw BCGException.genException(BCErrorEnum.INNER_EXCEPTION,  "无法从原始报文解析得到设备编码");
        }
        DeviceProductBo deviceProductBo =  protocolUtilService.queryInstanceByDeviceCode(deviceCode);
        if(null == deviceProductBo){
            throw BCGException.genException(BCErrorEnum.INNER_EXCEPTION, deviceCode + "无法找到对应的产品协议");
        }
        parseDeviceBo.setBaseProtocol(deviceProductBo.getBaseProtocol());
        parseDeviceBo.setDeviceCode(deviceCode);
        parseDeviceBo.setProductCode(deviceProductBo.getProductCode());
        return parseDeviceBo;
    }

    /**
     * 本方法内把所有可能获取deviceId的方式都试一遍，
     * 当然这里可以能会有优先级，比如同时匹配clientId和imei，那根据自己的业务决定到底以哪个为准
     * */
    private String parseDeviceCode(byte[] content){
        String deviceCode = this.parseWatch(content);
        if(!StringUtils.isEmpty(deviceCode)){
            return deviceCode;
        }

        deviceCode = this.parseSwitch(content);

        return deviceCode;
    }
    /**
     * 这样的函数可以多写几个，在这里把可能获取到设备编码的格式都解析一遍
     * */
    private String parseWatch(byte[] content){
        try{
            String str = new String(content, BCConstants.GLOBAL.CHARSET_UFT8);
            Map<String, Object> map = JSONProvider.parseObject(str, Map.class);
            return (String)map.get("imei");
        }catch (Exception e){
            log.warn("UDP从原始数据获取设备编码异常");
            return null;
        }
    }

    private String parseSwitch(byte[] content){
        try{
            String str = new String(content, BCConstants.GLOBAL.CHARSET_UFT8);
            Map<String, Object> map = JSONProvider.parseObject(str, Map.class);
            return (String)map.get("clientId");
        }catch (Exception e){
            log.warn("UDP从原始数据获取设备编码异常");
            return null;
        }
    }
}
